package battle_system

import (
	"confs/gen/common"
	"confs/gen/rpc_protos"
	"game/app/actors/schemas"
	"gos/bases/parse"
	"gos/modules/logger"
	"gos/services/gactor/actor"
	"sync"
)

// BattleBehaviorSystem
type BattleBehaviorSystem struct{}

type IBattleBehaviorSystem interface {
	Register(typ common.BattleEntityType, behavior IBattleBehavior)
	GetBehavior(typ common.BattleEntityType) (IBattleBehavior, bool)
	BattleRoundNotice(state *schemas.MoveState, serverId string, results []*common.BattleRoundPipe) error
	BattleEndNotice(state *schemas.MoveState, serverId string, report []*common.BattleReport) error
	BattleCreateNotice(state *schemas.MoveState, serverId string, battleId int64, attacker, defender *common.BattleTroop, attackInfo *common.BattleInfo, defenceInfo *common.BattleInfo) error
	BattleStickJumpNotice(state *schemas.MoveState, serverId string, id, targetId int64, data *common.MoveData) error
	BattleStickNotice(state *schemas.MoveState, serverId string, id, targetId int64, stick bool, data *common.MoveData) error
}

var BattleBehavior IBattleBehaviorSystem = BattleBehaviorSystem{}

// IBattleBehavior 战斗行为通用接口
type IBattleBehavior interface {
	BeginBattle(state *schemas.MoveState, entity *schemas.BattleEntity) bool
	EndBattle(state *schemas.MoveState, entity *schemas.BattleEntity, stop bool) bool
	RoundBegin(state *schemas.MoveState, entity *schemas.BattleEntity, battle *schemas.Battle)
	SetDead(state *schemas.MoveState, entity *schemas.BattleEntity)
}

var behaviors = sync.Map{}

// Register
func (s BattleBehaviorSystem) Register(typ common.BattleEntityType, behavior IBattleBehavior) {
	behaviors.Store(typ, behavior)
}

// GetBehavior
func (s BattleBehaviorSystem) GetBehavior(typ common.BattleEntityType) (IBattleBehavior, bool) {
	v, ok := behaviors.Load(typ)
	if !ok {
		logger.ERR("get battle behavior failed, behavior not exists, battle type: ", typ)
		return nil, false
	}
	return v.(IBattleBehavior), true
}

// BattleRoundNotice
func (s BattleBehaviorSystem) BattleRoundNotice(state *schemas.MoveState, serverId string, results []*common.BattleRoundPipe) error {
	return actor.RpcCast(serverId, &rpc_protos.MapRpcBattleRoundReq{
		RoundPipes: results,
	})
}

// BattleEndNotice
func (s BattleBehaviorSystem) BattleEndNotice(state *schemas.MoveState, serverId string, reports []*common.BattleReport) error {
	return actor.RpcCast(serverId, &rpc_protos.MapRpcBattleEndReq{
		Reports: reports,
	})
}

// BattleCreateNotice
func (s BattleBehaviorSystem) BattleCreateNotice(state *schemas.MoveState, serverId string, battleId int64, attacker, defender *common.BattleTroop, attackInfo *common.BattleInfo, defenceInfo *common.BattleInfo) error {
	return actor.RpcCast(serverId, &rpc_protos.MapRpcBattleCreateReq{
		Id:          battleId,
		AttackInfo:  attackInfo,
		DefenceInfo: defenceInfo,
		Attacker:    attacker,
		Defender:    defender,
	})
}

func (s BattleBehaviorSystem) BattleStickJumpNotice(state *schemas.MoveState, serverId string, id, targetId int64, data *common.MoveData) error {
	return actor.RpcCast(serverId, &rpc_protos.MapRpcBattleStickJumpReq{
		Id:       id,
		TargetId: targetId,
		Data:     data,
		ServerId: parse.ToInt64(serverId),
	})
}

func (s BattleBehaviorSystem) BattleStickNotice(state *schemas.MoveState, serverId string, id, targetId int64, stick bool, data *common.MoveData) error {
	return actor.RpcCast(serverId, &rpc_protos.MapRpcBattleStickReq{
		Id:       id,
		TargetId: targetId,
		Stick:    stick,
		Data:     data,
		ServerId: parse.ToInt64(serverId),
	})
}
